# reference: 20190509_线性判别分析.ipynb

import numpy as np
import pandas as pd
import os, sys
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

path = "./data/iris.csv"
data_df = pd.read_csv(path)
data_df.head(3)
label_arr = data_df['class'].unique()
label_dict = {value:ix for ix, value in enumerate(label_arr)}

data_df['y_label'] = data_df['class'].map(lambda x: label_dict[x])
sample_data_df = data_df.query("y_label in [0, 1] and petal_width in [.4, 1.]")

cols_list = list(sample_data_df.columns)
x_data = sample_data_df.sepal_length.values
y_data = sample_data_df.sepal_width.values
c_data = sample_data_df.y_label.values

plt.scatter(x_data, y_data, c=c_data)
plt.grid(True)
plt.xlabel("sepal_length")
plt.ylabel("sepal_width")
plt.savefig("4.12-sepal.png")

# 图4.13
part_cols_list = [i for i in cols_list if i in ['sepal_length', 'sepal_width', 'y_label']]
x_samp_data = sample_data_df[part_cols_list]

def mean_cov(x_data):
    x_mean = x_data.mean(axis = 0)
    x_center = x_data - x_mean
    return np.dot(x_center.T, x_center), x_mean.values
# 协防
cov_arr = np.zeros((x_samp_data.shape[1]-1, x_samp_data.shape[1]-1))
# 类均值向量
mean_arr = []
for ix, value in x_samp_data.groupby('y_label'):
    #v = value[['sepal_length', 'sepal_width', 'spetal_length', 'petal_width']]
    value = value.copy()
    value.drop('y_label',axis = 1, inplace = True)
    cov_result, mean_result = mean_cov(value)
    cov_arr += cov_result
    mean_arr.append(mean_result)

w_eigen = np.dot(np.linalg.inv(cov_arr), mean_arr[1] - mean_arr[0])
w_eigen_norm = w_eigen / np.sqrt((w_eigen ** 2).sum())
np.dot(x_samp_data.drop('y_label', axis =1),w_eigen_norm)

lda = LinearDiscriminantAnalysis(n_components=1, solver='eigen')
lda.fit(x_samp_data.drop('y_label', axis =1),c_data)
project_arr = lda.transform(x_samp_data.drop('y_label', axis =1))

k_value = w_eigen_norm[-1]/w_eigen_norm[0]
proj_x = (project_arr/k_value).flatten()
color_dict = {1: 'c', 0:'y'}

x_data = sample_data_df.sepal_length.values
y_data = sample_data_df.sepal_width.values
c_data = sample_data_df.y_label.values

plt.figure(figsize=(10,10))
plt.scatter(x_data, y_data, c=c_data,marker = 'v')
plt.plot(proj_x,project_arr,'r*-')
for ix, v in enumerate(x_data):
    plt.plot([proj_x[ix], v],[project_arr[ix],y_data[ix]],
    '{}-.'.format(color_dict[c_data[ix]]),linewidth=1)
plt.grid(False)
plt.text(-0.35,0.7,"line")
plt.xlabel("sepal_length")
plt.ylabel("sepal_width")
plt.savefig("4.13-LDA.png")